﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Linq;

namespace BlogExtractor {

	public enum Format { Forum, Google };

	/// <summary>
	/// A blog posting
	/// </summary>
	class Post {
		const string _postBeginsWith = "<div class='post-body";
		const string _postEndsWith = "<div class='post-footer'>";
		const string _paragraphTab = "[color=#404040]∙ ∙ ∙ ∙ [/color]";
		const string _paragraphSpace = "[color=#404040][size=1]\r\n∙[/size][/color]";
		const string _mapDiv = "<div class=\"map\">";
		string _content;

		#region Properties

		public string ID { get; set; }
		public string Title { set; get; }
		public string Url { set; get; }
		public string Summary { set; get; }
		public string Author { set; get; }

		/// <summary>
		/// The full contents, including formatting, of the post
		/// </summary>
		string Content {
			get {
				if (string.IsNullOrEmpty(_content)) { _content = Web.Content(this.Url);	}
				return _content;
			}
		}

		/// <summary>
		/// The body of the post
		/// </summary>
		internal string Body {
			get {
				string text = this.Content;
				if (string.IsNullOrEmpty(text)) { throw new FormatException("post content not found"); }
				int start = text.IndexOf(_postBeginsWith);
				int end = text.IndexOf(_postEndsWith);
				if (start < 1 || end  < 1) { throw new FormatException("post body not found in text"); }
				return text.Substring(start, end - start);
			}
		}

		#endregion

		/// <summary>
		/// Load all posts at the given URL
		/// </summary>
		internal static List<Post> Load(string url) {
			try {
				var xml = XElement.Parse(Web.Content(url));
				XNamespace ns = xml.Attribute("xmlns").Value;
				return (from e in xml.Elements(ns + "entry")
						select new Post {
							ID = e.Element(ns + "id").Value,
							Title = e.Element(ns + "title").Value,
							Summary = e.Element(ns + "summary").Value,
							Author = e.Element(ns + "author").Element(ns + "name").Value,
							Url = e.Elements(ns + "link")
									.FirstOrDefault(el => el.Attribute("rel").Value == "alternate")
										.Attribute("href").Value,

						}).ToList();
			} catch {
				return null;
			}
		}

		string ReplaceSpecialCharacters(string text) {
			text = text.Replace("&#8217;", "’");
			text = text.Replace("&#8230;", "…");
			text = text.Replace("&#8220;", "“");
			text = text.Replace("&#8221;", "”");
			text = text.Replace("&#8212;", "—");
			text = text.Replace("&amp;", "&");
			text = text.Replace("&#160;", " ");
			return text;
		}

		internal string ToGoogleDoc() {
			string text = this.Body;
			int start = text.IndexOf("<p>");
			int end = text.LastIndexOf("</p>") + 4;
			text = text.Substring(start, end - start);
			text = Regex.Replace(text, @"_(\w{10})_b.jpg", "_$1_s.jpg");
			text = text.Replace("<div class=\"photo\">", "");
			text = text.Replace("</div>", "");
			text = this.ReplaceSpecialCharacters(text);
			return text;
		}

		internal string ToBBCode() {
			string text = this.Body;
			// now trim it down to the exact paragraphs
			int start = text.IndexOf("<p>");
			int quoteStart = text.IndexOf("<blockquote>");
			if (quoteStart >= 0 && quoteStart < start) { start = quoteStart; }
			int end = text.LastIndexOf("</p>");
			text = text.Substring(start, (end - start) + 4);

			text = Regex.Replace(text, @"<em>([\w\s]+)</em>", "[i]$1[/i]");
			text = Regex.Replace(text, @"<strong>([\w\s]+)</strong>", "[b]$1[/b]");
			text = this.ReplaceSpecialCharacters(text);

			// block quote
			text = text.Replace("<blockquote>", "[indent][indent][size=-1]");
			text = text.Replace("</blockquote>", "[/size][/indent][/indent]");

			// paragraphs
			//text = Regex.Replace(text, @"</p>\s*<p>", "</p>" + _paragraphSpace + "<p>");
			text = Regex.Replace(text, @"\s*</p>\s*", "[/indent]");
			text = Regex.Replace(text, @"\s*<p>\s*", "[indent]" + _paragraphTab);

			// expand relative links
			text = Regex.Replace(text, @"href=""/", "href=\"" + Program.Profile.BlogUrl + "/");

			// link
			text = Regex.Replace(text,
				@"<a href=""([^""]+)"">([^<]+)</a>",
				"[url=$1]$2[/url]");
			// image
			text = Regex.Replace(text,
				@"<div class=""photo""><img[alt=""\s]+src=""([^""]+)""[alt=""\s]*/></div>",
				Environment.NewLine + Environment.NewLine +
				"[center][img]$1[/img][/center]" + Environment.NewLine);
			// image with caption
			text = Regex.Replace(text,
				@"<div class=""photo""><img[alt=""\s]+src=""([^""]+)""[alt=""\s]*/>\s*<div>([^<]+)\s*</div>\s*</div>",
				Environment.NewLine + Environment.NewLine +
				"[center][img]$1[/img]" + Environment.NewLine +
				"[font=Tahoma][size=-1][b]$2[/b][/size][/font][/center]" + Environment.NewLine);

			// map
			start = text.IndexOf(_mapDiv);
			if (start > 0) {
				text = text.Replace(_mapDiv, "[center]");
				end = text.IndexOf("</div>", start);
				text = text.Substring(0, end) + "[/center]" + text.Substring(end + 6);
			}

			text = "[font=Georgia, Times New Roman][size=+1]" + text + "[/size][/font]";

			return text;
		}
	}
}
